﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;
using l1cs.server.model.Instance;
using l1cs.server.utils;
using l1cs.server.datatables;
using l1cs.server.model.gametime;
using l1cs.server.model.skill;

namespace l1cs.server.model
{
    class Dungeon
    {
        private static Logger _log = Logger.getLogger( typeof( Dungeon ).FullName );

        private static Dungeon _instance = null;

        private Dictionary<String, NewDungeon> _dungeonMap = new Dictionary<String, NewDungeon>();

        private enum DungeonType
        {
            NONE, SHIP_FOR_FI, SHIP_FOR_HEINE, SHIP_FOR_PI, SHIP_FOR_HIDDENDOCK,
            SHIP_FOR_GLUDIN, SHIP_FOR_TI
        }

        private struct NewDungeon
        {
            public int _newX;
            public int _newY;
            public short _newMapId;
            public int _heading;
            public DungeonType _dungeonType;

            public NewDungeon( int newX, int newY, short newMapId, int heading, DungeonType dungeonType )
            {
                _newX = newX;
                _newY = newY;
                _newMapId = newMapId;
                _heading = heading;
                _dungeonType = dungeonType;

            }
        }

        public static Dungeon getInstance()
        {
            if ( _instance == null )
            {
                _instance = new Dungeon();
            }
            return _instance;
        }

        private Dungeon()
        {
            String sqlstr = "SELECT * FROM dungeon";
            using ( MySqlWrapper wrapper = new MySqlWrapper() )
            {
                foreach ( DataRow item in wrapper.GetDataTable( sqlstr ).Rows )
                {
                    int srcMapId = SqlUtils.toInt( item["src_mapid"] );
                    int srcX = SqlUtils.toInt( item["src_x"] );
                    int srcY = SqlUtils.toInt( item["src_y"] );
                    String key = String.Format( "{0}{1}{2}", srcMapId, srcX, srcY );
                    int newX = SqlUtils.toInt( item["new_x"] );
                    int newY = SqlUtils.toInt( item["new_y"] );
                    int newMapId = SqlUtils.toInt( item["new_mapid"] );
                    int heading = SqlUtils.toInt( item["new_heading"] );
                    DungeonType dungeonType = DungeonType.NONE;
                    if ( ( srcX == 33423 || srcX == 33424 || srcX == 33425
                      || srcX == 33426 ) && srcY == 33502 && srcMapId == 4 // ハイネ船着場->FI行きの船
                      || ( srcX == 32733 || srcX == 32734 || srcX == 32735
                      || srcX == 32736 ) && srcY == 32794 && srcMapId == 83 )
                    { // FI行きの船->ハイネ船着場
                        dungeonType = DungeonType.SHIP_FOR_FI;
                    }
                    else if ( ( srcX == 32935 || srcX == 32936 || srcX == 32937 )
                          && srcY == 33058 && srcMapId == 70 // FI船着場->ハイネ行きの船
                          || ( srcX == 32732 || srcX == 32733 || srcX == 32734
                          || srcX == 32735 ) && srcY == 32796 && srcMapId == 84 )
                    { // ハイネ行きの船->FI船着場
                        dungeonType = DungeonType.SHIP_FOR_HEINE;
                    }
                    else if ( ( srcX == 32750 || srcX == 32751 || srcX == 32752 )
                          && srcY == 32874 && srcMapId == 445 // 隠された船着場->海賊島行きの船
                          || ( srcX == 32731 || srcX == 32732 || srcX == 32733 )
                          && srcY == 32796 && srcMapId == 447 )
                    { // 海賊島行きの船->隠された船着場
                        dungeonType = DungeonType.SHIP_FOR_PI;
                    }
                    else if ( ( srcX == 32296 || srcX == 32297 || srcX == 32298 )
                          && srcY == 33087 && srcMapId == 440 // 海賊島船着場->隠された船着場行きの船
                          || ( srcX == 32735 || srcX == 32736 || srcX == 32737 )
                          && srcY == 32794 && srcMapId == 446 )
                    { // 隠された船着場行きの船->海賊島船着場
                        dungeonType = DungeonType.SHIP_FOR_HIDDENDOCK;
                    }
                    else if ( ( srcX == 32630 || srcX == 32631 || srcX == 32632 )
                          && srcY == 32983 && srcMapId == 0 // TalkingIsland->TalkingIslandShiptoAdenMainland
                          || ( srcX == 32733 || srcX == 32734 || srcX == 32735 )
                          && srcY == 32796 && srcMapId == 5 )
                    { // TalkingIslandShiptoAdenMainland->TalkingIsland
                        dungeonType = DungeonType.SHIP_FOR_GLUDIN;
                    }
                    else if ( ( srcX == 32540 || srcX == 32542 || srcX == 32543
                          || srcX == 32544 || srcX == 32545 ) && srcY == 32728
                          && srcMapId == 4 // AdenMainland->AdenMainlandShiptoTalkingIsland
                          || ( srcX == 32734 || srcX == 32735 || srcX == 32736
                          || srcX == 32737 ) && srcY == 32794 && srcMapId == 6 )
                    { // AdenMainlandShiptoTalkingIsland->AdenMainland
                        dungeonType = DungeonType.SHIP_FOR_TI;
                    }
                    NewDungeon newDungeon = new NewDungeon( newX, newY, (short)newMapId, heading, dungeonType );
                    if ( _dungeonMap.ContainsKey( key ) )
                    {
                        _log.log( Level.WARNING, "同じキーのdungeonデータがあります。key=" + key );
                    }
                    _dungeonMap[key] = newDungeon;
                }
            }
        }

        public bool dg( int locX, int locY, int mapId, L1PcInstance pc )
        {
            int servertime = L1GameTimeClock.getInstance().currentTime().getSeconds();
            int nowtime = servertime % 86400;
            String key = new StringBuilder().Append( mapId ).Append( locX ).Append( locY ).ToString();
            if ( _dungeonMap.ContainsKey( key ) )
            {
                NewDungeon newDungeon = _dungeonMap[key];
                short newMap = newDungeon._newMapId;
                int newX = newDungeon._newX;
                int newY = newDungeon._newY;
                int heading = newDungeon._heading;
                DungeonType dungeonType = newDungeon._dungeonType;
                bool teleportable = false;

                if ( dungeonType == DungeonType.NONE )
                {
                    teleportable = true;
                }
                else
                {
                    if ( nowtime >= 15 * 360 && nowtime < 25 * 360 // 1.30~2.30
                            || nowtime >= 45 * 360 && nowtime < 55 * 360 // 4.30~5.30
                            || nowtime >= 75 * 360 && nowtime < 85 * 360 // 7.30~8.30
                            || nowtime >= 105 * 360 && nowtime < 115 * 360 // 10.30~11.30
                            || nowtime >= 135 * 360 && nowtime < 145 * 360
                            || nowtime >= 165 * 360 && nowtime < 175 * 360
                            || nowtime >= 195 * 360 && nowtime < 205 * 360
                            || nowtime >= 225 * 360 && nowtime < 235 * 360 )
                    {
                        if ( ( pc.getInventory().checkItem( 40299, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_GLUDIN ) // TalkingIslandShiptoAdenMainland
                                || ( pc.getInventory().checkItem( 40301, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_HEINE ) // AdenMainlandShiptoForgottenIsland
                                || ( pc.getInventory().checkItem( 40302, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_PI ) )
                        { // ShipPirateislandtoHiddendock
                            teleportable = true;
                        }
                    }
                    else if ( nowtime >= 0 && nowtime < 360
                          || nowtime >= 30 * 360 && nowtime < 40 * 360
                          || nowtime >= 60 * 360 && nowtime < 70 * 360
                          || nowtime >= 90 * 360 && nowtime < 100 * 360
                          || nowtime >= 120 * 360 && nowtime < 130 * 360
                          || nowtime >= 150 * 360 && nowtime < 160 * 360
                          || nowtime >= 180 * 360 && nowtime < 190 * 360
                          || nowtime >= 210 * 360 && nowtime < 220 * 360 )
                    {
                        if ( ( pc.getInventory().checkItem( 40298, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_TI ) // AdenMainlandShiptoTalkingIsland
                                || ( pc.getInventory().checkItem( 40300, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_FI ) // ForgottenIslandShiptoAdenMainland
                                || ( pc.getInventory().checkItem( 40303, 1 )
                                && dungeonType == DungeonType.SHIP_FOR_HIDDENDOCK ) )
                        { // ShipHiddendocktoPirateisland
                            teleportable = true;
                        }
                    }
                }

                if ( teleportable )
                {
                    // 2秒間は無敵（アブソルートバリア状態）にする。
                    pc.setSkillEffect( L1SkillId.ABSOLUTE_BARRIER, 2000 );
                    pc.stopHpRegeneration();
                    pc.stopMpRegeneration();
                    pc.stopMpRegenerationByDoll();
                    L1Teleport.teleport( pc, newX, newY, newMap, heading, false );
                    return true;
                }
            }
            return false;
        }
    }
}
